/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.suli.roll.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import me.zhengjie.entity.Result;
import me.zhengjie.suli.outHouse.service.OrdersService;
import me.zhengjie.suli.roll.domain.Roll;
import me.zhengjie.suli.rollDetail.domain.RollDetail;
import me.zhengjie.suli.rollDetail.repository.RollDetailRepository;
import me.zhengjie.suli.toHouse.domain.Receipt;
import me.zhengjie.suli.toHouse.domain.ReceiptDetail;
import me.zhengjie.suli.toHouse.repository.ReceiptDetailRepository;
import me.zhengjie.suli.toHouse.repository.ReceiptRepository;
import me.zhengjie.util.CommonUtil;
import me.zhengjie.util.UuidUtil;
import me.zhengjie.utils.ValidationUtil;
import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import me.zhengjie.suli.roll.repository.RollRepository;
import me.zhengjie.suli.roll.service.RollService;
import me.zhengjie.suli.roll.service.dto.RollDto;
import me.zhengjie.suli.roll.service.dto.RollQueryCriteria;
import me.zhengjie.suli.roll.service.mapstruct.RollMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import me.zhengjie.utils.PageUtil;
import me.zhengjie.utils.QueryHelp;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
 * @author WYH
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2024-03-14
 **/
@Service
@RequiredArgsConstructor
public class RollServiceImpl implements RollService {

    private final RollRepository rollRepository;
    private final RollMapper rollMapper;
    private final CommonUtil commonUtil;
    private final RollDetailRepository rollDetailRepository;
    private final OrdersService ordersService;
    private final ReceiptDetailRepository receiptDetailRepository;
    @Value("${sccs.port}")
    private String sccsPort;

    @Value("${sccs.ip}")
    private String sccsIp;

    @Value("${agv.ip}")
    private String agvIp;

    @Value("${agv.port}")
    private String agvPort;
    private final ReceiptRepository receiptRepository;

    @Override
    public Map<String, Object> queryAll(RollQueryCriteria criteria, Pageable pageable) {
        Page<Roll> page = rollRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(rollMapper::toDto));
    }

    @Override
    public List<RollDto> queryAll(RollQueryCriteria criteria) {
        return rollMapper.toDto(rollRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public RollDto findById(String id) {
        Roll roll = rollRepository.findById(id).orElseGet(Roll::new);
        ValidationUtil.isNull(roll.getId(), "Roll", "id", id);
        return rollMapper.toDto(roll);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RollDto create(Roll resources) {
        resources.setId(IdUtil.simpleUUID());
        return rollMapper.toDto(rollRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Roll resources) {
        Roll roll = rollRepository.findById(resources.getId()).orElseGet(Roll::new);
        ValidationUtil.isNull(roll.getId(), "Roll", "id", resources.getId());
        roll.copy(resources);
        rollRepository.save(roll);
    }

    @Override
    public void deleteAll(String[] ids) {
        for (String id : ids) {
            rollRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<RollDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (RollDto roll : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("转仓单号", roll.getRollCode());
            map.put("从库区", roll.getFromWano());
            map.put("至库区", roll.getToWano());
            map.put("数量", roll.getMrQty());
            map.put("类型", roll.getType());
            map.put("状态", roll.getStatus());
            map.put("创建时间", roll.getCreateTime());
            map.put("创建人", roll.getCreateBy());
            map.put("修改时间", roll.getUpdateTime());
            map.put("来源单据", roll.getSourceDocument());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Object getNotRestricted(String param) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("list", param);
        Roll bySourceDocument = rollRepository.findBySourceDocument(param);
        if (null != bySourceDocument){
            return  null;
        }
        String s = commonUtil.httpPost(sccsIp + ":" + sccsPort + "/RTDSXWMS/WMSSelectList", jsonObject.toJSONString());
        String resp = StrUtil.strip(s, "\"").replaceAll("\\\\", "");
        JSONObject jsonObject1 = JSON.parseObject(resp);
        if (jsonObject1.getBoolean("tran_flg")) {
            List<JSONObject> jsonObjectList = JSON.parseArray(jsonObject1.getString("message"), JSONObject.class);
            Roll roll = new Roll();
            if (jsonObjectList.get(0).getString("mt_area").equals("0015") || jsonObjectList.get(0).getString("mt_area").equals("S015") || jsonObjectList.get(0).getString("mt_area").equals("B015")) {
                roll.setType("出库");
            } else {
                roll.setType("入库");
            }
            Snowflake snowflake = new Snowflake();
            roll.setId(snowflake.nextIdStr());
            roll.setRemk(jsonObject1.getString("remk"));
            roll.setStatus("未开始");
            roll.setCreateBy("admin");
            roll.setSourceDocument(param);
            roll.setFromWano(jsonObjectList.get(0).getString("mt_area"));
            roll.setToWano(jsonObjectList.get(0).getString("mt_tarea"));
            roll.setCreateTime(new Timestamp(new Date().getTime()));
            roll.setRollCode(UuidUtil.genCode());
            List<RollDetail> rollDetails = new ArrayList<>();
            BigDecimal bigDecimal = new BigDecimal(0);
            for (JSONObject object : jsonObjectList) {
                RollDetail rollDetail = new RollDetail();
                rollDetail.setId(snowflake.nextIdStr());
                rollDetail.setMainId(roll.getId());
                rollDetail.setStatus("未开始");
                rollDetail.setElNo(object.getString("el_no"));
                rollDetail.setElUnit(object.getString("el_unit"));
                rollDetail.setElName(object.getString("el_name"));
                rollDetail.setFromWaNo(object.getString("mt_area"));
                rollDetail.setToWaNo(object.getString("mt_tarea"));
                rollDetail.setLotNo(object.getString("lot_no"));
                if (roll.getType().equals("出库")) {
                    rollDetail.setMrQty(object.getBigDecimal("mr_qty"));
                } else {
                    rollDetail.setMrQty(object.getBigDecimal("mr_qty"));
                }

                rollDetail.setPkList(object.getString("pk_list"));
                bigDecimal = bigDecimal.add(null != rollDetail.getMrQty() ? rollDetail.getMrQty() : new BigDecimal(0));
                rollDetails.add(rollDetail);
            }
            roll.setMrQty(bigDecimal);
            rollRepository.save(roll);
            rollDetailRepository.saveAll(rollDetails);
            if (roll.getType().equals("出库")) {
                try {
                    return rollDetails;
//                    String id = ordersService.outBoundNotRestricted(rollDetails, roll);
//                    Object o = ordersService.addOutBoundTask(id);
//                    return JSON.toJSONString(o);
                } catch (Exception e) {
                    return "0";
                }

            } else {
                /** 调拨出库业务 */
                /** 生成装仓入库单 */

                /** 根据不同的物料应该要拆分转仓单 */
                List<Receipt> receiptList = new ArrayList<>();  // 不重复的receipt主表
                for (RollDetail rollDetail : rollDetails) {
                    int flag = 0;
                    /** 判断是否有相同的物料  */
                    for (Receipt receipt : receiptList) {
                        if (receipt.getElNo().equals(rollDetail.getElNo())) {   // 如果物料编码相同，不另外生成Receipt了
                            ReceiptDetail receiptDetailForRoll = new ReceiptDetail();
                            receiptDetailForRoll.setId(IdUtil.simpleUUID());
                            receiptDetailForRoll.setReceiptDetailCode(UuidUtil.genCode());
                            receiptDetailForRoll.setStatus(1);  // 1--未完成入库
                            receiptDetailForRoll.setPkList(rollDetail.getPkList()); // 箱号
                            receiptDetailForRoll.setPkQty(rollDetail.getMrQty());   // 入库数量
                            receiptDetailForRoll.setReceiptId(receipt.getId());
                            receipt.setPkQty(receipt.getPkQty().add(receiptDetailForRoll.getPkQty()));
                            receiptRepository.save(receipt);
                            receiptDetailRepository.save(receiptDetailForRoll);
                            flag = 1;
                            break;
                        }
                    }
                    if (flag == 0) {    // 没有相同物料的入库单
                        Receipt receipt = new Receipt();
                        receipt.setId(snowflake.nextIdStr());
                        receipt.setReceiptCode(UuidUtil.genCode());
                        receipt.setMtList(roll.getSourceDocument());   // 转仓单的源单号（A2024030817885类似，业主的内部单号）
                        receipt.setStatus("0");
                        receipt.setChNo(roll.getRollCode());
                        receipt.setElNo(rollDetail.getElNo());  // 物料编码
                        receipt.setElName(rollDetail.getElName());  //物料名称
                        receipt.setPkQty(rollDetail.getMrQty());    // 计划数量
                        receipt.setActQty(new BigDecimal(0));   // 已入库数量
                        receipt.setElUnit(rollDetail.getElUnit());  // 单位
                        receipt.setLotNo(rollDetail.getLotNo());    // 批次号
                        receipt.setVmiCode("N");    //  是否VMI物料
                        receipt.setIsSendSccs(0); // 是否推送SCCS
                        receipt.setMtArea(rollDetail.getToWaNo());    // 入库库位
                        receipt.setMtBwart("转仓入库");  // 移动类型 311-非限制库存转仓
                        receiptRepository.save(receipt);
                        receiptList.add(receipt);   // 加入收货单主表

                        ReceiptDetail receiptDetailForRoll = new ReceiptDetail();
                        receiptDetailForRoll.setId(IdUtil.simpleUUID());
                        receiptDetailForRoll.setReceiptDetailCode(UuidUtil.genCode());
                        receiptDetailForRoll.setStatus(1);  // 1--未完成入库
                        receiptDetailForRoll.setPkList(rollDetail.getPkList()); // 箱号
                        receiptDetailForRoll.setPkQty(rollDetail.getMrQty());   // 入库数量
                        receiptDetailForRoll.setReceiptId(receipt.getId());
                        receiptDetailRepository.save(receiptDetailForRoll);
                    }
                }
                JSONObject respObject = new JSONObject();
                respObject.put("code", 200);
                respObject.put("msg", "success");
                return respObject.toJSONString();
            }
        } else {
            return "1";
        }
    }
}